package My

import (
	"fmt"
	"db2s/ETL"
	"db2s/global"
	"strings"
)

func (my TableInfoMeta) TriggerExist(s global.TablesMetaInfoInput) (result global.ObjectExistReturnResult, err error) {
	var f1 any
	var event = "[MySQLTriggerExist]"
	result.BaseResult.Sql = fmt.Sprintf("select count(1) as `sum` from information_schema.TRIGGERS where TRIGGER_SCHEMA = '%v' and TRIGGER_NAME='%v'", s.TableInfo.Schema, s.TableInfo.Table)
	if result.BaseResult.TimeOut, f1, err = ExecSelectSql(ExecSqlInputS{
		Ss:           s,
		Event:        event,
		SelectSqlStr: result.BaseResult.Sql,
		Expect:       ETL.Map,
	}); err != nil || f1 == nil {
		return
	}
	if fmt.Sprintf("%v", f1.(map[string]any)["sum"]) == "1" {
		result.Result = true
	}
	return
}

func (my TableInfoMeta) TriggerName(s global.TablesMetaInfoInput) (result global.ObjectNameReturnResult, err error) {
	var f1 any
	var event = "[MySQLTriggerName]"
	result.BaseResult.Sql = fmt.Sprintf("select TRIGGER_NAME from information_schema.TRIGGER_SCHEMA where  TRIGGER_SCHEMA ='%v' %v",
		s.TableInfo.Schema, func() string {
			switch {
			case s.TableInfo.Table == "*":
				return ""
			case strings.Contains(s.TableInfo.Table, "%"):
				return fmt.Sprintf(" and TRIGGER_NAME like '%%%v%%'", s.TableInfo.Table)
			default:
				return fmt.Sprintf(" and TRIGGER_NAME = '%v'", s.TableInfo.Table)
			}
		}())
	if result.BaseResult.TimeOut, f1, err = ExecSelectSql(ExecSqlInputS{
		Ss:           s,
		Event:        event,
		SelectSqlStr: result.BaseResult.Sql,
		Expect:       ETL.StringGarth,
	}); err != nil || f1 == nil {
		return
	}
	result.Result = f1.([]string)
	return
}

func TriggerPrintInfo(x *global.TriggerResultDefinition) (res string) {
	return fmt.Sprintf("CREATE TRIGGER `%v`.`%v` \n"+
		"\t%v %v ON `%v`\n"+
		"\tFOR EACH %v\n"+
		"\t-- 触发器逻辑\n    "+
		"\t %v \n"+
		"\t;",
		x.Schema, x.Name,
		x.Timing, x.MonitorEvent, x.MonitorTable,
		x.Orientation, x.Body,
	)
}
func (my SchemaObjectMeta) Trigger(s global.SchemaObjectInput) (result global.SchemaObjectReturnResult, err error) {
	var (
		f1    any
		event = "[MySQLTrigger]"
		x     global.TriggerResultDefinition
	)
	result.BaseResult.Sql = fmt.Sprintf("SELECT\n"+
		"\t`TRIGGER_SCHEMA` AS `schema`,\n"+
		"\t`TRIGGER_NAME` AS `name`,\n"+
		"\t`DEFINER`  AS `definer`,\n"+
		"\t-- `ACTION_REF` AS `type`,-- BEFORE STATEMENT 语句级别，AFTER EACH ROW行级别\n"+
		"\t`ACTION_ORIENTATION` as `orientation`,  -- 方向是ROW还是SQL\n"+
		"\t`ACTION_TIMING`  as `timing`,    -- 定义是before 还是after\n"+
		"\t`EVENT_MANIPULATION` AS `monitorEvent`, \n"+
		"`EVENT_OBJECT_SCHEMA` AS `monitorSchema`, \n"+
		"\t`EVENT_OBJECT_TABLE` AS `monitorTable`,\n"+
		"\t`ACTION_CONDITION` AS `caseWhen`,\n"+
		"\t`ACTION_STATEMENT` AS `body`,\n"+
		"\t`TRIGGER_STATUS` AS `status`  \n"+
		"FROM\n"+
		"\tINFORMATION_SCHEMA.`TRIGGERS` "+
		"WHERE 1=1 AND TRIGGER_SCHEMA = '%v' AND TRIGGER_NAME = '%v' \n"+
		s.Schema, s.Table)
	if result.BaseResult.TimeOut, f1, err = ExecSelectSql(ExecSqlInputS{
		Ss:           s,
		Event:        event,
		SelectSqlStr: result.BaseResult.Sql,
		Expect:       ETL.Map,
	}); err != nil || f1 == nil {
		return
	}
	if err = global.MapSubToStructSubJsonName(mapNullActive(f1.(map[string]any)), &x); err != nil {
		return
	}
	x.Type = "trigger"
	x.PrintInfo = TriggerPrintInfo(&x)
	result.TriggerResult.Definition = x
	result.TriggerResult.Convert = global.TriggerDefinitionConvertS{
		Schema:       x.Schema,
		Name:         x.Name,
		TriggerType:  x.TriggerType,
		MonitorEvent: x.MonitorEvent,
		MonitorTable: x.MonitorTable,
		CaseWhen:     x.CaseWhen,
		Comment:      x.Comment,
		Body:         x.Body,
		Frequency:    x.Frequency,
		Status:       x.Status,
		Type:         x.Type,
		PrintInfo:    x.PrintInfo,
	}
	return
}

func singleTriggerBody(s string) (res string) {
	res = s
	res = strings.ReplaceAll(res, ":OLD", "OLD")
	res = strings.ReplaceAll(res, ":NEW", "NEW")
	res = strings.TrimSpace(res)
	if strings.HasSuffix(res, "/") {
		res = strings.TrimSpace(res[:len(res)-1])
	}
	if strings.HasSuffix(res, ";") {
		res = strings.TrimSpace(res[:len(res)-1])
	}
	return
}

func singleTriggerCreateSql(q global.TriggerObjectResult, schema, event string) (res string) {
	var (
		triggerName = q.Definition.Name
	)
	if !strings.EqualFold(q.Definition.MonitorEvent, event) {
		triggerName = strings.TrimSpace(fmt.Sprintf("%v_%v", triggerName, event))
	}
	return fmt.Sprintf("delimiter /\n"+
		"CREATE TRIGGER `%v`.`%v` \n"+
		"\t%v %v ON `%v`\n"+
		"\tFOR EACH ROW\n"+
		"\t-- 触发器逻辑\n    "+
		"\t %v \n"+
		"\t/\n"+
		"delimiter ;\n",
		schema, triggerName,
		q.Convert.Timing, event, q.Convert.MonitorTable,
		singleTriggerBody(q.Convert.Body),
	)
}
func createTrigger(s global.SchemaObjectInput) (res global.ObjectFixSqlS, err error) {
	var q = s.ObjectDefinition.TriggerResult
	res.CreateSql = append(res.CreateSql, fmt.Sprintf("use `%v`;", s.Schema))
	for _, v := range q.Convert.TriggerEventGarth {
		res.CreateSql = append(res.CreateSql, singleTriggerCreateSql(q, s.Schema, v))
	}
	return
}
